#include "stm32f4xx.h"                  // Device header
#include "stm32f4xx_conf.h"
#include "Delay.h"

uint16_t V_REF=1489;//V_REF校验值(大概率1496,不确定),若无校验V_REF有默认值1489(1.2/3.3*4095,默认V_DDA为3.3V)

/*
 *函数简介:V_REF校验
 *参数说明:无
 *返回类型:无
 *备注:用ADC1采集1000次V_REF,将平均值四舍五入作为V_REF的校验值
 *备注:ADC为非连续非扫描独立模式,单通道无DMA,数据右对齐,分辨率为12bits,软件触发
 *备注:校验完成关闭V_REF通道和ADC1
 *备注:ADCCLK=PCLK/ADC_Prescaler预分频值=84MHz/ADC_Prescaler,默认2分频,ADCCLK=42MHz(大约0.024us)
 *备注:转换一次所需时间:T=采样周期+转换周期=(采样周期+分辨率)*ADCCLK,默认T=(56+12)*(1/42MHz)≈1.62us
 *备注:V_REF校验大约耗时1~2ms
 *备注:经过测试,此速度基本上是最快速度
 */
void VREF_Verify(void)
{
	uint32_t Sum=0;//1000次转换求和值
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);//开启时钟
	
	ADC_CommonInitTypeDef ADC_CommonInitStructure;
	ADC_CommonInitStructure.ADC_Mode=ADC_Mode_Independent;//独立模式
	ADC_CommonInitStructure.ADC_DMAAccessMode=ADC_DMAAccessMode_Disabled;//不开启DMA
	ADC_CommonInitStructure.ADC_Prescaler=ADC_Prescaler_Div2;//预分频为2
	ADC_CommonInitStructure.ADC_TwoSamplingDelay=ADC_TwoSamplingDelay_5Cycles;//2个采样阶段之间的延迟,在双重或三重交错模式下使用,此处随意设置
	ADC_CommonInit(&ADC_CommonInitStructure);
	
	ADC_InitTypeDef ADC_InitStructure;
	ADC_InitStructure.ADC_ContinuousConvMode=DISABLE;//配置为非连续转换
	ADC_InitStructure.ADC_ScanConvMode=DISABLE;//配置为非扫描
	ADC_InitStructure.ADC_DataAlign=ADC_DataAlign_Right;//配置为数据右对齐
	ADC_InitStructure.ADC_NbrOfConversion=1;//通道数1
	ADC_InitStructure.ADC_Resolution=ADC_Resolution_12b;//分辨率为12bits
	ADC_InitStructure.ADC_ExternalTrigConv=ADC_ExternalTrigConv_Ext_IT11;//外部事件选择,软件触发下此位无意义
	ADC_InitStructure.ADC_ExternalTrigConvEdge=ADC_ExternalTrigConvEdge_None;//配置为软件触发(不使用外部触发)
	ADC_Init(ADC1,&ADC_InitStructure);//初始化ADC1
	
	ADC_TempSensorVrefintCmd(ENABLE);//开启温度传感器和V_REF的通道
	ADC_Cmd(ADC1,ENABLE);//启动ADC1
	Delay_s(1);//等待唤醒
	
	for(uint16_t i=0;i<1000;i++)
	{
		ADC_RegularChannelConfig(ADC1,ADC_Channel_17,1,ADC_SampleTime_56Cycles);//选择规则组输入通道ADC1通道ADC_Channel_17(V_REF)为序列1,采样时间56ADCCLK
		ADC_SoftwareStartConv(ADC1);//软件触发转换开始
		while(ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC)==RESET);//等待转换完成
		Sum+=ADC_GetConversionValue(ADC1);//返回转换值,并求和
	}
	
	if(Sum/100%10>4)V_REF=Sum/1000+1;//四舍五入获取V_REF校验值
	else V_REF=Sum/1000;
	ADC_TempSensorVrefintCmd(DISABLE);//关闭温度传感器和V_REF的通道
	ADC_Cmd(ADC1,DISABLE);//关闭ADC1
}
